Interprétation par syntaxe abstraite d'ordre supérieur et traduction en combinateurs
نویسنده
چکیده
ions. Une abstraction pouvant être utilisée en dehors du contexte où elle est définie, on doit mémoriser la liaison des variables apparaissant dans son corps au moment de sa définition. C’est à cette fin qu’on utilise une fermeture, c’est-à-dire l’association d’une abstraction (ident * term) et de l’environnement dans lequel elle a été définie (env) via le constructeur ValAbs. Lecture/écriture mémoire. La mémoire, elle aussi, est gérée par un environnement (store). Bien que celui-ci puisse être géré de manière purement fonctionnelle, nous utilisons une variable globale impérative afin de simplifier l’écriture de l’interprète3. De plus, l’utilisation d’une liste d’associations pour représenter la mémoire est naı̈ve et peut être remplacée indifféremment par une autre structure plus efficace. Fonctions prédéfinies. Comme les constantes entières, les fonctions prédéfinies ne sont pas modifiées par l’évaluation. Conditionnelle. L’évaluation d’une conditionnelle n’évalue que la branche then ou else selon le résultat de l’évaluation de la condition. 3. Syntaxe abstraite d’ordre supérieur Comme nous l’avons mentionné plus tôt, nous souhaitons déléguer totalement au langage hôte la tâche de réduction des applications. Ce choix est justifié en raison de la simplicité du code correspondant (le noyau de l’évaluateur sera très concis), de son efficacité potentielle (OCaml est connu pour gérer efficacement les applications de fonctions) et de sa grande abstraction (une unique notion de fonction est nécessaire). Ceci est mis en œuvre avec une syntaxe abstraite d’ordre supérieur. La syntaxe abstraite d’ordre supérieur consiste à représenter des abstractions/liaisons de variables (λ, ∀, ∃ ou autres) dans un arbre de syntaxe par des lambda-expressions (Pfenning et al., 1988), représentées ici par les fonctions du langage hôte. On peut transformer la syntaxe abstraite term donnée plus tôt en syntaxe d’ordre supérieur en supprimant les abstractions et les variables, les mécanismes d’applications de fonctions reposeront alors sur ceux du langage hôte : type term os = and value = | Int os of int | ValInt of int | App os of term os * term os | ValFun of value -> value | Fun os of value -> value Un seul constructeur est nécessaire pour désigner à la fois les fonctions prédéfinies et les fonctions définies par l’utilisateur car elles sont représentées dans les deux cas par une fonction du type value -> value du langage hôte. Par exemple, la fonction fun (x) = x+1 peut être représentée par : 3. La version purement fonctionnelle nécessite de faire le choix d’un ordre d’évaluation dans les applications, ce qui n’est pas fait dans la version exposée ici. Interprétation par ordre supérieur 1145 Fun os (fun x -> app (app plus x) ValInt 1) où app est définie par : app (Fun os f) v = f v. Ceci est vrai également pour le type value : la construction ValAbs dénotant les fermetures n’est plus nécessaire. Nous n’incluons pas de construction pour la conditionnelle if dans cette syntaxe car elle peut être vue comme une fonction particulière. En effet le if peut être vu comme une fonction à trois arguments qui n’évalue pas tous ses arguments (une fonction non stricte). Dans la section 5 nous verrons qu’on peut l’encoder par une fonction ordinaire. Les traits impératifs peuvent également être encodés dans cette syntaxe (section 6). Le choix de ne pas intégrer la conditionnelle ou les traits impératifs dans le type term os se justifie par l’objectif de ne pas compliquer le cœur de l’interprète quitte à recourir à des transformations syntaxiques en amont afin de se conformer à ce type. L’évaluation des termes en syntaxe d’ordre supérieur se fait de la manière suivante : let rec eval os = function | Int os i -> ValInt i | Fun os f -> ValFun f | App os (t1,t2) -> (match (eval os t1, eval os t2) with (Fun os f, v) -> f v ) On voit bien ici que c’est le langage hôte qui gère l’application (f v). L’utilisation d’une syntaxe d’ordre supérieur a les avantages suivants : – les fonctions prédéfinies et les fonctions définies par l’utilisateur peuvent être traitées uniformément, – les variables ne sont plus gérées par l’interprète mais par le langage hôte, ceci signifie notamment que l’on n’a pas besoin de gérer : la portée des variables dans toutes les manipulations de l’arbre de syntaxe (les optimisations par exemple), l’instanciation des variables lors de l’application, la propagation d’environnements (ou de substitutions). Ces avantages permettent d’avoir un interprète plus concis et donc : – plus simple à développer, comportant moins d’erreurs, plus maintenable, – plus simple à décrire, sur lequel on peut mieux raisonner, – plus propice à l’expérimentation. La difficulté liée à cette approche est la production des valeurs fonctionnelles par l’analyse syntaxique ou comme résultat d’un calcul. Plus précisément, l’approche décrite ici pose 3 problèmes. Problème P1 : production des fonctions du langage hôte. Dans OCaml comme dans le λ-calcul, le seul moyen de renvoyer une fonction est de renvoyer une fonction 1146 RSTI TSI – 26/2007. Langages applicatifs prédéfinie ou d’en créer une par application d’autres fonctions. A moins d’utiliser des outils spécifiques pour la programmation multiniveau, un calcul ne peut pas créer une fonction en utilisant l’abstraction comme on le fait en écrivant un programme. Problème P2 : intégration des fonctions non strictes. Les fonctions non strictes comme la conditionnelle if-then-else, le ou et le et paresseux ne peuvent être directement traduits en fonctions OCaml. En effet, si on traduit le if-then-else par une fonction à trois arguments, les trois arguments seront évalués puisque OCaml est un langage à appel par valeurs. Problème P3 : intégration des traits impératifs. Comme les fonctions non strictes, les traits impératifs ne s’expriment pas tous comme des fonctions. C’est le cas de la mise en séquence qui ne peut être vue comme une fonction à deux arguments (à moins d’avoir une garantie sur l’ordre d’évaluation des arguments4). Par ailleurs même si un trait impératif peut être vu comme une fonction, comme c’est le cas avec la fonction print, il faut veiller à ce que l’effet de bord ait lieu au (( bon moment )) . Par exemple, on souhaite que l’évaluation de l’expression suivante imprime 1 avant 0 : (fun (x) = print "0") (print "1") Notre réponse au problème P1 est la décomposition en combinateurs (section 4). Celle aux problèmes P2 et P3 est l’utilisation de glaçons (sections 5 et 6). Grâce à ces solutions techniques, l’évaluation des termes du langage considéré suit le schéma suivant : 1 2 3 cu rry fic ati on , gla ço ns programme source term programme curryfié cterm combinateurs expression de
منابع مشابه
Higher-Order Abstract Syntax with Induction in Coq
Three important properties of Higher-Order Abstract Syntax are the (higher-order) induction principle, which allows proofs by induction, the (higher-order) injection principle, which asserts that equal terms have equal heads and equal sons, and the exten-sionality principle, which asserts that functional terms which are pointwise equal are equal. Higher-order abstract syntax is implemented for ...
متن کاملHigher-order Abstract Syntax in Coq Higher-order Abstract Syntax in Coq
The terms of the simply-typed-calculus can be used to express the higher-order abstract syntax of objects such as logical formulas, proofs, and programs. Support for the manipulation of such objects is provided in several programming languages (e.g. Prolog, Elf). Such languages also provide embedded implication, a tool which is widely used for expressing hypothetical judgments in natural deduct...
متن کاملSpécification et Vérification par Interprétation Abstraite d’Aspects pour la Distribution
Nous présentons une méthode pour spécifier et vérifier des programmes en séparant les préoccupations. En particulier, nous décrivons la spécification puis la vérification par interprétation abstraite de programmes distribués. Un programme est composé de deux parties, une partie concurrente et une partie fonctionnelle. Elles sont ensuite composées en utilisant un mécanisme de tissage simple (syn...
متن کاملSPARQL Template : un langage de pretty printing pour RDF
RDF est un langage de représentation de connaissances basé sur des graphes étiquetés, conçu par le W3C pour le Web sémantique et le Web des données. En tant que langage d’échange pivot, il peut être utilisé pour représenter des arbres de syntaxe abstraite (AST) de langages. Par exemple le langage OWL a plusieurs syntaxes dont une syntaxe fonctionnelle et une syntaxe RDF, de même que le langage ...
متن کاملUn Syst Eme Pour L'optimisation Globale De Programmes D'ordre Sup Erieur Par Compilation Abstraite S Epar Ee
Le pr esent document a et e r edig e dans le cadre de la deuxi eme partie de l'examen pr edoctoral de Dominique Boucher sous la direction du professeur Marc Feeley. La proposition consiste en l'architecture d'un compilateur pour un langage fonctionnel d'ordre sup erieur capable de r ealiser des optimisations intermodules. Le syst eme utilise une technique d'implantation des analyses statiques b...
متن کاملذخیره در منابع من
با ذخیره ی این منبع در منابع من، دسترسی به آن را برای استفاده های بعدی آسان تر کنید
برای دانلود متن کامل این مقاله و بیش از 32 میلیون مقاله دیگر ابتدا ثبت نام کنید
ثبت ناماگر عضو سایت هستید لطفا وارد حساب کاربری خود شوید
ورودعنوان ژورنال:
- Technique et Science Informatiques
دوره 26 شماره
صفحات -
تاریخ انتشار 2007